package com.xinxing.city.recovery.serialport;

import android.util.Log;

import com.xinxing.city.recovery.APPRuntime;
import com.xinxing.city.recovery.Constant;
import com.xinxing.city.recovery.DI;
import com.xinxing.city.recovery.entitys.KernelAction;
import com.xinxing.city.recovery.entitys.KernelActions;
import com.xinxing.city.recovery.interfaces.ICallBackWeight;
import com.xinxing.city.recovery.interfaces.IDeviceKernel;
import com.xinxing.city.recovery.interfaces.IDoorState;
import com.xinxing.city.recovery.interfaces.IOverFlowListener;
import com.xinxing.city.recovery.interfaces.ISerialSendReceiveData;
import com.xinxing.city.recovery.interfaces.MockListener;
import com.xinxing.city.recovery.utils.StringUtil;

import org.greenrobot.eventbus.EventBus;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;


public class MockSerai implements ISerialSendReceiveData {
    private ICallBackWeight callBackWeight;
    private MockListener mockListener;
    private APPRuntime appRuntime;

    @Override
    public void start(String sPort, int iBaudRate, IDeviceKernel kernel) {
        appRuntime = DI.getInstance(APPRuntime.class);
        mockListener = new MockListener() {
            @Override
            public void onDataReceived(byte[] buffer, int size) {
                String res = StringUtil.byte2HexStr(buffer);
                Log.e("Serial", res);
                List<String> params8 = new ArrayList<>();
                params8.add(res);
                EventBus.getDefault().post(new KernelAction(KernelActions.LOG, params8));
                switch (buffer[2]) {
                    case (byte) 0x11://门操作
                        int roomNumber = buffer[3];
                        int roomState = buffer[4];
                        roomState(roomNumber, buffer[4]);
                        break;
                    case (byte) 0x13://称重
                        if (buffer[4] == 1) {
                            int roomNumber2 = buffer[3];
                            long weightotal = bytesToInt2(new byte[]{buffer[5], buffer[6], buffer[7], buffer[8]});
                            long pi = appRuntime.getPiWeight().get(roomNumber2);
                            weightotal = weightotal - pi;
                            if (weightotal < 0) {
                                weightotal = 0;
                            }

                            weightState(roomNumber2, weightotal);
//                                anyWeight.put(roomNumber2,weightotal);
                            appRuntime.setAnyWeight(roomNumber2, weightotal);
                            callBackWeight.setWeight(roomNumber2, weightotal);
                        } else if (buffer[4] == 2) {
                            //清零
                        }
                        break;
                    case (byte) 0x17://开门锁
                        break;
                    case (byte) 0x15://故障
                        Log.e("TTT", "故障码：" + buffer[3] + "   数据：" + buffer[4]);
                        Constant.FaultCode = buffer[3];
                        Constant.FaultData = buffer[4];
                        break;
                    case (byte) 0x14://满溢
                        if (buffer[4] == 1) {//满溢状态,数据：00未满01满溢 02压缩（仅一号位）
                            Constant.OVERRLOW.put((int) buffer[3], (int) buffer[5]);
//                                overFlowListener.overFlowState(overFlow1,overFlow2,overFlow3,overFlow4);
                            List<String> params = new ArrayList<>();
                            params.add(String.valueOf((int) buffer[3]));
                            if (buffer[5] == 1) {
                                EventBus.getDefault().post(new KernelAction(KernelActions.OVERRLOW, params));
                            }
                            if (buffer[5] == 2) {
                                EventBus.getDefault().post(new KernelAction(KernelActions.ZIP, params));
                            }
                        } else if (buffer[4] == 2) {//投口状态, 数据：00关门完成 01开门 02关门中
//                                if( Constant.DOOR_STATE.containsKey((int)buffer[3])){
//
//                                    int type = Constant.DOOR_STATE.get((int)buffer[3]);
//                                    Log.e("serial ","Type:  "+type+"   bu "+(int)buffer[5]);
//                                    if(type != (int)buffer[5]){
//                                        Constant.DOOR_STATE.put((int) buffer[3], (int) buffer[5]);
//                                        List<String> params = new ArrayList<>();
//                                        params.add(String.valueOf((int) buffer[3]));
//                                        EventBus.getDefault().post(new KernelAction(KernelActions.DOOR_START, params));
//                                    }
//                                }else {
                            Constant.DOOR_STATE.put((int) buffer[3], (int) buffer[5]);
                            List<String> params = new ArrayList<>();
                            params.add(String.valueOf((int) buffer[3]));
                            EventBus.getDefault().post(new KernelAction(KernelActions.DOOR_START, params));
//                                }
                        } else if (buffer[4] == 3) {//清运门状态,数据：00清运门关闭 01清运门开启
                            Constant.CLEAN_DOOR_STATE.put((int) buffer[3], (int) buffer[5]);
                            List<String> params = new ArrayList<>();
                            params.add(String.valueOf((int) buffer[3]));
                            EventBus.getDefault().post(new KernelAction(KernelActions.CLEAN_DOOR_START, params));
                        }


                        break;
                    case (byte) 0x80://关门上报
                        int roomNum = buffer[4];
                        int errorCode = buffer[3];
                        int errorCount = buffer[5];
                        if (errorCount > 5) {
                            Log.e("Serial", roomNum + "号关门次数超过5次失败,错误码：" + errorCode);
                        }
                        break;
                }
            }
        };
    }

    @Override
    public void stop() {

    }

    @Override
    public void openDoor(int doornum) {
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x07);
        mbuffer.add((byte) 0x11);
        mbuffer.add((byte) doornum);
        mbuffer.add((byte) 0x01);
        mbuffer.addAll(getCrc16(mbuffer));
        byte[] bytes = new byte[mbuffer.size()];
        for (int i = 0; i < mbuffer.size(); i++) {
            bytes[i] = mbuffer.get(i);
        }
        mockListener.onDataReceived(bytes, 1);
    }

    @Override
    public void closeDoor(int doornum) {
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x07);
        mbuffer.add((byte) 0x11);
        mbuffer.add((byte) doornum);
        mbuffer.add((byte) 0x00);
        mbuffer.addAll(getCrc16(mbuffer));
        byte[] bytes = new byte[mbuffer.size()];
        for (int i = 0; i < mbuffer.size(); i++) {
            bytes[i] = mbuffer.get(i);
        }
        mockListener.onDataReceived(bytes, 1);
    }

    @Override
    public void getWeight(int doornum, ICallBackWeight callBackWeight) {
        this.callBackWeight = callBackWeight;
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x0B);
        mbuffer.add((byte) 0x13);
        mbuffer.add((byte) doornum);
        mbuffer.add((byte) 0x01);
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x00);
        if (doornum == 1 || doornum == 4) {
            mbuffer.add((byte) 0x64);
            mbuffer.add((byte) 0x3A);
        }else if(doornum ==2){
            mbuffer.add((byte) 0x2E);
            mbuffer.add((byte) 0xE0);
        }else if(doornum ==3){
            mbuffer.add((byte) 0x36);
            mbuffer.add((byte) 0xB0);
        }
        mbuffer.addAll(getCrc16(mbuffer));
        byte[] bytes = new byte[mbuffer.size()];
        for (int i = 0; i < mbuffer.size(); i++) {
            bytes[i] = mbuffer.get(i);
        }
        mockListener.onDataReceived(bytes, 1);

    }

    @Override
    public void getWeightReset(int doornum) {

    }

    @Override
    public void getWeightCorrect1(int doornum) {

    }

    @Override
    public void getWeightCorrect2(int doornum) {

    }

    @Override
    public void openCut(int doornum) {

    }

    @Override
    public void closeCut(int doornum) {

    }

    @Override
    public void openZip(int doornum) {

    }

    @Override
    public void closeZip(int doornum) {

    }

    @Override
    public void openLock(int doornum) {

    }

    @Override
    public void overflow(IOverFlowListener overFlowListener) {

    }

    @Override
    public void setDoorState(IDoorState iDoorState) {

    }

    @Override
    public void sendSingleRfid() {

    }

    @Override
    public void sendLoopRfid() {

    }

    @Override
    public void fault() {

    }

    @Override
    public void getState() {

    }

    public void roomState(int roomNum, byte state) {
//        iDoorState.doorState(roomNum, state);
    }

    public static int bytesToInt2(byte[] bs) {

        int signedInt = ByteBuffer.wrap(bs).getInt();
        return signedInt;
    }

    public void weightState(int roomNum, long state) {

    }

    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i + 1), 16));
        }
        return data;
    }

    static ArrayList<Byte> getCrc16(ArrayList<Byte> arr_buff) {
        int len = arr_buff.size();

        // 预置 1 个 16 位的寄存器为十六进制FFFF, 称此寄存器为 CRC寄存器。
        int crc = 0xFFFF;
        int i, j;
        for (i = 0; i < len; i++) {
            // 把第一个 8 位二进制数据 与 16 位的 CRC寄存器的低 8 位相异或, 把结果放于 CRC寄存器
            crc = ((crc & 0xFF00) | (crc & 0x00FF) ^ (arr_buff.get(i) & 0xFF));
            for (j = 0; j < 8; j++) {
                // 把 CRC 寄存器的内容右移一位( 朝低位)用 0 填补最高位, 并检查右移后的移出位
                if ((crc & 0x0001) > 0) {
                    // 如果移出位为 1, CRC寄存器与多项式A001进行异或
                    crc = crc >> 1;
                    crc = crc ^ 0xA001;
                } else
                    // 如果移出位为 0,再次右移一位
                    crc = crc >> 1;
            }
        }
        return intToBytes2_fx(crc);
    }

    private static ArrayList<Byte> intToBytes2_fx(int value) {
        ArrayList<Byte> src = new ArrayList<Byte>();
        byte b1 = (byte) ((value >> 8) & 0xFF);
        byte b0 = (byte) (value & 0xFF);
        src.add(b0);
        src.add(b1);

        return src;
    }
}
